package com.rpc.example.spring.customer;

import com.rpc.example.IRegitserService;
import com.rpc.example.constant.Constant;
import com.rpc.example.constant.RequestTypeEnum;
import com.rpc.example.constant.SerializeTypeEnum;
import com.rpc.example.core.ClientFuture;
import com.rpc.example.core.Header;
import com.rpc.example.core.Protocol;
import com.rpc.example.core.Request;
import com.rpc.example.core.RequestHolder;
import com.rpc.example.core.Response;
import com.rpc.example.protocol.NettyClient;
import io.netty.channel.DefaultEventLoop;
import io.netty.util.concurrent.DefaultPromise;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

@Slf4j
public class InvokeProxy implements InvocationHandler {

    private IRegitserService registerService;
    private String applicationName;

    public InvokeProxy(IRegitserService registerService, String applicationName) {
        this.registerService = registerService;
        this.applicationName = applicationName;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("+++++代理执行+++++++");
        Protocol<Request> protocol = new Protocol<>();
        Header header = new Header();
        header.setMagic(Constant.MAGIC);
        header.setSerializeType(SerializeTypeEnum.JAVA.getCode());
        header.setRequestType(RequestTypeEnum.REQUEST.getCode());
        long requestId = RequestHolder.REQUEST_ID.getAndDecrement();
        header.setRequestId(requestId);
        header.setDataLength(0);
        protocol.setHeader(header);
        Request request = new Request(applicationName, method.getDeclaringClass().getName(), method.getName(), args, method.getParameterTypes());
        protocol.setData(request);
        NettyClient nettyClient = new NettyClient();
        nettyClient.sendRequest(protocol, registerService);
        ClientFuture<Response> response = new ClientFuture<>(new DefaultPromise<>(new DefaultEventLoop()));
        RequestHolder.FUTURE_MAP.put(protocol.getHeader().getRequestId(), response);
        return response.getPromise().get().getContent();
    }
}
